home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
drdobbs
/
1987
/
08
/
bowlst.aug
next >
Wrap
Text File
|
1987-08-12
|
15KB
|
405 lines
1: /*
2: *
3: * KROSS.C
4: *
5: * COPYRIGHT (C) 1987 by Charles F. Bowman
6: *
7: * ALL RIGHTS RESERVED.
8: *
9: */
10: #include "stdio.h"
11:
12: #define NIL '\000'
13:
14: #define ALL 1
15: #define PUZ 2
16: #define DOWN 1
17: #define ACROSS 2
18:
19: #define MINWORD 3
20: #define MAXPUZ 25
21: #define MAXWORD 50
22: #define WORDLEN 15
23:
24: #define EMPTY 0
25: #define FREE 1
26: #define USED 2
27: #define SOLVED 3
28:
29: #define BLANK ' '
30: #define PADCHAR '-'
31: #define WORDS "@words"
32: #define PUZZLE "@puzzle"
33:
34: #define FLAG(x, y) list[ x - MINWORD ].w[ y ].flg
35: #define WORD(x, y) list[ x - MINWORD ].w[ y ].word
36:
37: FILE *fp;
38: int length, width;
39: char puzzle[ MAXPUZ ][ MAXPUZ ];
40:
41: struct words {
42: char word[ WORDLEN ];
43: int flg;
44: };
45:
46: struct {
47: struct words w[ MAXWORD ];
48: } list[ WORDLEN - MINWORD ];
49:
50: main( ac, av )
51: int ac;
52: char *av[];
53: {
54:
55: if( ac != 2 ){
56: fprintf( stderr, "usage: kross puzzlefile\n" );
57: exit( 1 );
58: }
59: if( (fp = fopen( av[1], "r" )) == NULL ){
60: fprintf( stderr, "Cannot open '%s' to read!\n", av[1] );
61: exit( 2 );
62: }
63:
64: readpuz( fp );
65: if( solve(0, -1) ){
66: pprint( PUZ );
67: } else {
68: printf( "No Solution!!\n" );
69: }
70: exit( 0 );
71: }
72:
73: /*
74: * =============================================================
75: * READPUZ(): read puzzle into memory from file
76: * =============================================================
77: */
78: readpuz()
79: {
80: int i;
81: char buf[ 85 ];
82:
83:
84: length = 0;
85: /*
86: * Puzzle Section
87: */
88: if( fgets( buf, sizeof buf, fp ) == NULL ){
89: fprintf( stderr, "%s: Premature EOF!\n", PUZZLE );
90: exit( 4 );
91: }
92: if( strncmp( buf, PUZZLE, strlen( PUZZLE ) ) ){
93: fprintf( stderr, "%s: BAD FORMAT!\n", PUZZLE );
94: exit( 5 );
95: }
96:
97: if(fgets(buf,sizeof buf,fp)==NULL
98: || !strncmp(buf,WORDS,strlen(WORDS))){
99: fprintf( stderr, "%s: Premature EOF!\n", PUZZLE );
100: exit( 4 );
101: }
102: width = strlen( buf ) - 1;
103:
104: do {
105: if( (strlen( buf ) - 1) != width ){
106: fprintf(stderr,"Line %d: bad width!\n", width);
107: exit( 5 );
108: }
109: for( i = 0; i < width; i++ ){
110: if( buf[ i ] == BLANK ){
111: puzzle[ length ][ i ] = NIL;
112: } else if( buf[i] == PADCHAR ){
113: puzzle[ length ][ i ] = buf[ i ];
114: } else {
115: fprintf(stderr,"BAD CHAR '%d' L# %d\n",
116: buf[i], length );
117: exit( 88 );
118: }
119: }
120: puzzle[ length ][ width ] = NIL;
121: length += 1;
122: } while(fgets(buf,sizeof buf,fp)!=NULL &&
123: strncmp( WORDS, buf, strlen(WORDS) ) != 0 );
124:
125: /*
126: * Words Section
127: */
128: while( fgets( buf, sizeof buf, fp ) != NULL ){
129: for( i = 0; i < MAXWORD; i++ ){
130: if( FLAG( strlen(buf) - 1, i ) == EMPTY ){
131: strncpy( WORD( strlen(buf) - 1, i ),
132: buf, strlen(buf)-1 );
133: FLAG( strlen(buf) - 1, i ) = FREE;
134: }
135: }
136: if( i >= MAXWORD ){
137: fprintf( stderr, "Out of space %d %s\n",
138: strlen(buf)-1, buf );
139: exit( 6 );
140: }
141: }
142: return;
143: }
144:
145: /*
146: * =============================================================
147: * PPRINT(): display solved pzzle
148: * =============================================================
149: */
150: pprint( t )
151: int t;
152: {
153: int i, j;
154:
155: switch( t ){
156: case ALL:
157: /*
158: * Debug only!
159: */
160: for( i = MINWORD; i < WORDLEN; i++ ){
161: j = 0;
162: while( WORD(i, j)[0] != NIL ){
163: printf( "%s\n", WORD(i, j) );
164: j++;
165: }
166: }
167:
168: case PUZ:
169: for( i = 0; i < length; i++ ){
170: for( j = 0; j < width; j++ ){
171: if( puzzle[ i ][ j ] ){
172: putchar( puzzle[ i ][ j ] );
173: } else {
174: putchar( BLANK );
175: }
176: }
177: putchar( '\n' );
178: }
179: }
180:
181: return;
182: }
183:
184: /*
185: * =============================================================
186: * SOLVE(): function that searches for a solution
187: * =============================================================
188: */
189: static int s = 0;
190: static int prev = -1;
191:
192: solve( length, width )
193: int length, width;
194: {
195: int l, w, i, len, tmp, type;
196: char old[ WORDLEN - MINWORD + 1 ];
197:
198: w = width;
199: l = length;
200: len = next( &l, &w, &type );
201: if( len == 0 )
202: return( SOLVED );
203:
204: for( i = 0; i < MAXWORD && WORD(len, i)[0] != NIL; i++ ){
205: if( FLAG(len, i) == FREE
206: && itfits(l, w, WORD(len, i), type) ){
207: FLAG(len, i) = USED;
208: enter( old, l, w, WORD(len, i), type );
209: prev = type;
210: tmp = solve( l, w );
211: if( tmp == SOLVED )
212: return( SOLVED );
213: restore( old, l, w, type );
214: FLAG(len, i) = FREE;
215: }
216: }
217:
218: return( 0 );
219: }
220:
221: /*
222: * =============================================================
223: * NEXT(): locate next slot to fill
224: * =============================================================
225: */
226: next( len, wht, t )
227: int *len, *wht, *t;
228: {
229: /*
230: * Return the next slot in the puzzle to attempt
231: * to be solved. DOWN has precedence.
232: *
233: * The new values for len & wht will be updated.
234: * The returned value for the 'w' coordinate for
235: * an across 'hit' will have to be the value + 1.
236: */
237: int l, w, tmp;
238:
239: l = *len;
240: w = *wht;
241:
242: /*
243: * Check current position for across: down would
244: * have been done already.
245: */
246: if( w != -1 && ( (w - 1) < 0 || puzzle[l][w-1] == NIL )
247: && puzzle[l][w] && (w + 1) < width && puzzle[l][w+1] ){
248: /*
249: * Across!
250: */
251: *t = ACROSS;
252:
253: /*
254: * Neccessary Evil!
255: */
256: *wht = w + 1;
257:
258: tmp = 0;
259: while( puzzle[l][w] != NIL && w < width ){
260: w += 1;
261: tmp += 1;
262: }
263: return( tmp );
264:
265: } else if( prev == DOWN || w == -1 ){
266: w += 1;
267: }
268:
269: /*
270: * Check for next possible position
271: */
272: for(; l < length; l += 1 ){
273: for(; w < width; w += 1 ){
274: if( ( (l - 1) < 0 || puzzle[l-1][w] == NIL )
275: && puzzle[l][w] != NIL && (l + 1) < length
276: && puzzle[l+1][w] != NIL ){
277: /*
278: * Down!
279: */
280: *t = DOWN;
281: prev = DOWN;
282: *wht = w;
283: *len = l;
284: tmp = 0;
285: while(puzzle[l][w]!=NIL && l<length){
286: l += 1;
287: tmp += 1;
288: }
289: return( tmp );
290: }
291: if( ((w - 1) < 0 || puzzle[l][w-1] == NIL)
292: && puzzle[l][w] && (w+1) < width
293: && puzzle[l][w+1] ){
294: /*
295: * Across!
296: */
297: *t = ACROSS;
298: prev = ACROSS;
299: *len = l;
300: *wht = w + 1;
301:
302: tmp = 0;
303: if( w == -1 ) w = 0;
304: while(puzzle[l][w] != NIL && w<width){
305: w += 1;
306: tmp += 1;
307: }
308: return( tmp );
309: }
310: }
311: w = 0;
312: }
313:
314: /*
315: * Puzzle Completed!
316: */
317: return( 0 );
318: }
319:
320: /*
321: * =============================================================
322: * ITFITS(): determine is a word fits into a slot
323: * =============================================================
324: */
325: itfits( l, w, word, t )
326: char *word;
327: int t;
328: {
329: char *cp;
330:
331: if( t == ACROSS && w != -1)
332: w -= 1;
333:
334: cp = word;
335: while( *cp ){
336: if( *cp != puzzle[l][w] && puzzle[l][w] != PADCHAR )
337: return( 0 );
338: if( t == ACROSS )
339: w += 1;
340: else
341: l += 1;
342: cp++;
343: }
344: return( 1 );
345: }
346:
347: /*
348: * =============================================================
349: * ENTER(): enter word into puzzle
350: * =============================================================
351: */
352: enter( old, l, w, word, t )
353: char *old;
354: int l, w;
355: char *word;
356: int t;
357: {
358: char *cp;
359:
360: if( t == ACROSS )
361: w -= 1;
362:
363: cp = word;
364: while( *cp ){
365: *old++ = puzzle[l][w];
366: puzzle[l][w] = *cp;
367: if( t == ACROSS )
368: w += 1;
369: else
370: l += 1;
371: cp++;
372: }
373: *old = NIL;
374:
375: return;
376: }
377:
378: /*
379: * =============================================================
380: * RESTORE(): restore puzzle to prev state
381: * =============================================================
382: */
383: restore( old, l, w, t )
384: char *old;
385: int l, w, t;
386: {
387: char *cp;
388:
389: if( t == ACROSS )
390: w -= 1;
391:
392: cp = old;
393: while( *cp ){
394: puzzle[l][w] = *cp;
395: if( t == ACROSS )
396: w += 1;
397: else
398: l += 1;
399: cp++;
400: }
401:
402: return;
403: }